﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using AR;

namespace AuthorizedNavigation.Client.Services
{
    public static class AuthorizationService
    {

        #region RequiresRole

        public static readonly DependencyProperty RequiresRoleProperty =
            DependencyProperty.RegisterAttached(
                "RequiresRole",
                typeof(IEnumerable<string>),
                typeof(AuthorizationService),
                new PropertyMetadata(new string[0], AuthorizationService.RequiresRolePropertyChanged));

        private static void RequiresRolePropertyChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            AuthorizationService.Authorize(sender);
        }

        [TypeConverter(typeof(StringArrayConverter))]
        public static IEnumerable<string> GetRequiresRole(DependencyObject target)
        {
            return (IEnumerable<string>)target.GetValue(AuthorizationService.RequiresRoleProperty);
        }

        public static void SetRequiresRole(DependencyObject target, IEnumerable<string> value)
        {
            target.SetValue(AuthorizationService.RequiresRoleProperty, value);
        }

        #endregion


        #region TargetProperties

        public static readonly DependencyProperty TargetPropertiesProperty =
            DependencyProperty.RegisterAttached(
                "TargetProperties",
                typeof(IEnumerable<string>),
                typeof(AuthorizationService),
                new PropertyMetadata(new string[0], AuthorizationService.TargetPropertiesPropertyChanged));

        private static void TargetPropertiesPropertyChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            AuthorizationService.Authorize(sender);
        }

        [TypeConverter(typeof(StringArrayConverter))]
        public static IEnumerable<string> GetTargetProperties(DependencyObject target)
        {
            return (IEnumerable<string>)target.GetValue(AuthorizationService.TargetPropertiesProperty);
        }

        public static void SetTargetProperties(DependencyObject target, IEnumerable<string> value)
        {
            target.SetValue(AuthorizationService.TargetPropertiesProperty, value);
        }

        #endregion


    
        public static AuthorizationResult Authorize(object target)
        {
            if (target == null)
            {
                throw new ArgumentNullException("target");
            }

            if (DesignerProperties.IsInDesignTool)
            {
                return AuthorizationResult.Allowed;
            }

            // cast to dep object            
            DependencyObject dpTarget = target as DependencyObject;

            // get the required role(s) for this target
            var requiredRoleList = AuthorizationService.GetRequiresRole(dpTarget); 

            if (requiredRoleList.Count() > 0)
            {

                // check 'em
                foreach (var item in requiredRoleList)
                {
                    if (WebContext.Current.User.IsInRole(item))
                    {
                        return AuthorizationResult.Allowed;
                    }
                }

                // user hasn't got any of the required roles.  Set correct target property to reflect this.
                // if no specific properties are targetted, either hide or disable this control, depending on preference.

                // find target properties

                var targetProperties = AuthorizationService.GetTargetProperties(dpTarget);

                if (targetProperties.Count() == 0)
                {
                        // no target properties defined, use default

                        // default: disable
                        if (dpTarget is TextBlock)
                        {
                            dpTarget.SetValue(AuthorizationHelperClasses.GetDependencyProperty(dpTarget, "Opacity"), 0.5);
                        }
                        else
                        {
                            dpTarget.SetValue(AuthorizationHelperClasses.GetDependencyProperty(dpTarget, "IsEnabled"), false);
                        }
                }
                else
                {
                    foreach (var item in targetProperties)
                    {
                        AuthorizationHelperClasses.SetPropertyValueOnTarget(dpTarget, item);
                    }
                }

                return new AuthorizationResult("No access");
            }
            else
            {
                return AuthorizationResult.Allowed;
            }

        }

    }
}
